import roll
from machine import Pin
import time
import util
from mqtt import start_mqtt

# 硬件初始化
photo_sensor = Pin(27, Pin.IN, Pin.PULL_UP)  # 光电传感器（低电平触发）
motor_d13 = Pin(13, Pin.OUT, value=0)       # 换气电机风扇
cooling_fan = Pin(15, Pin.OUT, value=0)     # 散热风扇（初始关闭）
red_led = Pin(14, Pin.OUT)                  # 红色状态灯
button33 = Pin(33, Pin.IN, Pin.PULL_UP)     # 一键倒沙按钮
button32 = Pin(32, Pin.IN, Pin.PULL_UP)     # 换沙子初始化按钮

# 全局变量
is_cat_present = False          # 猫是否在盆内
cleanup_delay = 30              # 清理延迟（秒）
trigger_time_clear = None       # 触发清理的时间戳
close_fan_delay = 60            # 风扇关闭延迟基数（秒）
trigger_time_fan = None         # 换气风扇触发时间
trigger_time_cooling = None     # 散热风扇触发时间
cooling_delay = 15              # 散热风扇延迟关闭时间（秒）
debounce_time = 1000            # 去抖动时间（毫秒）
need_clear = 0                  # 清理触发标志
need_pouring_sand = 0           # 倒沙触发标志
local_dict = {}                 # 临时状态存储
fan_level = 1                   # 风扇档位（1-4）
last_cleanup_hour = None        # 上次清理小时数
button33_press_start = None     # 按钮33按下起始时间
button32_last_state = 1         # 按钮32上一状态（1为未按下）
button32_debounce = 0           # 按钮32去抖计时器

# 模式控制（默认手动模式）
mode = "manual"  # manual:手动模式, auto:自动模式, timer:定时模式

# 模式切换时重置状态
def reset_mode_state():
    """模式切换时重置相关状态变量"""
    global trigger_time_clear, trigger_time_fan, need_clear, need_pouring_sand
    global trigger_time_cooling, button33_press_start
    
    trigger_time_clear = None
    trigger_time_fan = None
    trigger_time_cooling = None
    need_clear = 0
    need_pouring_sand = 0
    button33_press_start = None
    
    # 确保所有执行器回到安全状态
    motor_d13.off()
    cooling_fan.off()
    print("模式切换，系统状态已重置")

# MQTT消息处理
def change_variable(topic_str, msg_str):
    global mode, need_clear, need_pouring_sand, trigger_time_fan, fan_level
    
    if topic_str == "catbox006" and msg_str == "on":
        print("收到打开一键倒沙指令")
        need_pouring_sand = 1
        
    elif topic_str == "clear006" and msg_str == "on":
        print("收到打开猫砂清理指令")
        need_clear=1
        
    elif topic_str == "openfan003":
        if msg_str == "on":
            print("收到打开通风指令")
            trigger_time_fan = time.time()
            fan_level = 1
            motor_d13.on()
        elif msg_str == "off":
            print("收到关闭通风指令")
            motor_d13.off()
            trigger_time_fan = None
        elif "#" in msg_str:
            try:
                parts = msg_str.split("#")
                if len(parts) == 2 and parts[0] == "on":
                    level = int(parts[1])
                    if 1 <= level <= 4:
                        fan_level = level
                        motor_d13.on()
                        trigger_time_fan = time.time()
                        print(f"通风档位设置为 {level}")
                    else:
                        print("通风档位需在1-4之间")
                else:
                    print("通风指令格式错误（正确: on#数字）")
            except ValueError:
                print("通风档位需为整数")
    
    # 模式切换处理
    elif topic_str == "manual006" and msg_str == "on" and mode != "manual":
        mode = "manual"
        reset_mode_state()
        print("已切换到手动模式")
    elif topic_str == "auto006" and msg_str == "on" and mode != "auto":
        mode = "auto"
        reset_mode_state()
        print("已切换到自动模式")
    elif topic_str == "timer006" and msg_str == "on" and mode != "timer":
        mode = "timer"
        reset_mode_state()
        print("已切换到定时模式")

# 倒沙操作实现
def perform_pouring_sand():
    global trigger_time_cooling
    print("执行一键倒沙操作")
    try:
        cooling_fan.on()
        roll.pouring_sand()
        trigger_time_cooling = time.time()  # 记录散热风扇启动时间
    except Exception as e:
        print(f"倒沙操作出错: {e}")
        cooling_fan.off()

# 倒沙逻辑处理
def handle_pouring_sand():
    global need_pouring_sand, button33_press_start
    
    # MQTT指令触发
    if need_pouring_sand == 1:
        print("一键倒沙语音唤起")
        perform_pouring_sand()
        need_pouring_sand = 0
        return
    
    # 按钮长按3秒触发
    button_state = button33.value() == 0  # 低电平为按下
    if button_state:
        if button33_press_start is None:
            button33_press_start = time.time()
        else:
            press_duration = time.time() - button33_press_start
            if press_duration >= 3:
                print("一键倒沙按钮长按触发")
                perform_pouring_sand()
                button33_press_start = None  # 重置避免重复触发
    else:
        button33_press_start = None

# 清理操作实现
def start_cleanup():
    print("开始清理")
    global trigger_time_fan, trigger_time_cooling
    try:
        motor_d13.off()
        cooling_fan.on()
        roll.clean_up_cat_poop()  # 执行清理
        motor_d13.on()
        trigger_time_fan = time.time()
        trigger_time_cooling = time.time()
    except Exception as e:
        cooling_fan.off()
        current_time = util.get_current_time()
        message = f"清理出错 {current_time}：{e}"
        try:
            util.send_wechat_message(message)
        except Exception as e:
            print(f"发送微信消息失败: {e}")
    print("清理完毕")

# 清理逻辑处理（含按钮去抖）
def handle_cleanup():
    global need_clear, button32_last_state, button32_debounce
    
    # MQTT指令触发
    if need_clear == 1:
        print("清理猫砂语音唤起")
        start_cleanup()
        need_clear = 0
        return
    
    # 按钮去抖处理（类似光电传感器逻辑）
    current_state = button32.value()
    if current_state != button32_last_state:
        button32_debounce = time.ticks_ms()
        button32_last_state = current_state
    else:
        if time.ticks_diff(time.ticks_ms(), button32_debounce) > debounce_time:
            if current_state == 0:  # 稳定按下状态
                print("猫砂清理按钮被按下")
                start_cleanup()

# 猫进出检测
def handle_cat_detection():
    global is_cat_present, trigger_time_clear
    photo_state = photo_sensor.value() == 0  # 低电平表示遮挡
    
    if photo_state and not is_cat_present:
        # 猫进入检测（带1秒去抖）
        if 'entry_timer' not in local_dict:
            local_dict['entry_timer'] = time.ticks_ms()
        elif time.ticks_diff(time.ticks_ms(), local_dict['entry_timer']) > debounce_time:
            is_cat_present = True
            red_led.on()
            print("猫已进入")
            trigger_time_clear = None  # 进入时取消清理触发
            del local_dict['entry_timer']

    elif not photo_state and is_cat_present:
        # 猫离开检测（带1秒去抖）
        if 'exit_timer' not in local_dict:
            local_dict['exit_timer'] = time.ticks_ms()
        elif time.ticks_diff(time.ticks_ms(), local_dict['exit_timer']) > debounce_time:
            is_cat_present = False
            red_led.off()
            print("猫离开了")
            trigger_time_clear = time.time()  # 记录离开时间，用于自动清理
            del local_dict['exit_timer']

# 定时清理逻辑（增强容错）
def handle_timer_cleanup():
    global last_cleanup_hour
    if mode != "timer":
        return

    try:
        current_time = util.get_current_time()
        # 时间格式容错处理
        if " " not in current_time or len(current_time.split()) < 2:
            print(f"时间格式错误: {current_time}")
            return
            
        time_part = current_time.split()[1]
        if ":" not in time_part or len(time_part.split(":")) < 1:
            print(f"时间格式错误: {current_time}")
            return
            
        hour = int(time_part.split(':')[0])
        
        # 每天8点和20点触发，且避免同一小时重复执行
        if hour in [8, 20] and hour != last_cleanup_hour and not is_cat_present:
            print(f"定时清理触发：{current_time}")
            start_cleanup()
            last_cleanup_hour = hour
    except Exception as e:
        print(f"定时清理出错: {e}")

# 风扇和清理逻辑协调
def handle_cleanup_and_fan():
    global trigger_time_clear, trigger_time_fan, trigger_time_cooling
    
    # 自动模式下的延迟清理
    if mode == "auto" and trigger_time_clear:
        if (time.time() - trigger_time_clear) > cleanup_delay and not is_cat_present:
            start_cleanup()
            trigger_time_clear = None
    
    # 换气风扇自动关闭
    if trigger_time_fan:
        if (time.time() - trigger_time_fan) > close_fan_delay * fan_level:
            motor_d13.off()
            trigger_time_fan = None
            print("换气风扇关闭")
    
    # 风扇异常状态处理
    if motor_d13.value() == 1 and trigger_time_fan is None:
        print("检测到风扇异常开启，强制关闭")
        motor_d13.off()
    
    # 散热风扇自动关闭
    if trigger_time_cooling and (time.time() - trigger_time_cooling) > cooling_delay:
        cooling_fan.off()
        trigger_time_cooling = None
        print("散热风扇关闭")

# 在全局变量部分添加状态监控
system_start_time = time.time()
last_status_report = 0
status_report_interval = 1800  # 30分钟报告一次状态

# 添加系统状态报告函数
def report_system_status():
    global last_status_report
    current_time = time.time()
    if current_time - last_status_report > status_report_interval:
        try:
            uptime = current_time - system_start_time
            hours = uptime // 3600
            minutes = (uptime % 3600) // 60
            modestr="手动模式"
            if mode == "manual":
                modestr="手动"
            elif mode == "auto":
                modestr="自动"
            elif mode == "timer":
                modestr="定时"
            status_msg = f"模式: {modestr}, 运行时间: {int(hours)}小时{int(minutes)}分钟"
            util.send_wechat_message(status_msg)
            last_status_report = current_time
        except Exception as e:
            print(f"状态报告失败: {e}")

# 主逻辑
def main(): 
    handle_pouring_sand()
    handle_cleanup()
    handle_cat_detection()
    handle_cleanup_and_fan()
    handle_timer_cleanup()
    report_system_status()
    
# 初始化
motor_d13.off()  # 确保风扇初始关闭
start_mqtt(change_variable)
print("设备已启动，默认模式：手动模式")

# 主循环
while True:
    main()
    time.sleep_ms(20)  # 降低CPU占用